/***
 * java线程池完成定时任务DEMO
 * @author hy
 * @date 2018/6/7
 *
 */
public class DemoTask {

     /**
     * 线程池
     */
    private static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(4);

    /**
     * 同步信号量
     */
    private static final Semaphore MAX_STOCK_COUNT = new Semaphore(4);



    /**
     * 加入Throwable抛出异常，运行时不会异常结束任务
     * 当前定时每周第六天执行
     */
    private static Runnable TodoEverPresentTask = new Runnable() {
        @Override
        public synchronized void run() {
            try {
                MAX_STOCK_COUNT.acquire();
                Calendar c = Calendar.getInstance();
                int day = c.get(Calendar.DAY_OF_WEEK) - 1;
                int saturday = 6;
                if (day == saturday) {
                    System.out.println("执行每周六任务");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            } finally {
                MAX_STOCK_COUNT.release();
                everPresentDayTask();
            }
        }
    };


    /**
     * 定时器每天十点触发，然后执行TodoEverPresentTask，由TodoEverPresentTask判断执行时机
     * 运行时就获取当前时间
     * scheduleAtFixedRate（执行任务，延迟时间，循环时间，时间单位）
     */
    public static void everPresentDayTask() {

        scheduler = Executors.newScheduledThreadPool(1);
        synchronized (scheduler) {
            long oneDay = 24 * 60 * 60 * 1000L;
            long initDelay = getTimeMillis("22:00:00") - System.currentTimeMillis();
            initDelay = initDelay > 0 ? initDelay : oneDay + initDelay;
            scheduler.scheduleAtFixedRate(
                    TodoEverPresentTask,
                    initDelay,
                    oneDay,
                    TimeUnit.MILLISECONDS);
        }
    }


    /**
     * 加入Throwable抛出异常，运行时不会异常结束任务
     * 当前定时每月第一天和第六天执行
     */
    private static Runnable TodoEverPastTask = new Runnable() {
        @Override
        public synchronized void run() {
            try {
                MAX_STOCK_COUNT.acquire();
                Calendar c = Calendar.getInstance();
                Locale.setDefault(Locale.CHINESE);
                int day = c.get(Calendar.DAY_OF_MONTH);
                int everyMonthOne = 1;
                int everyMonthSix = 6;
                if (day == everyMonthOne || day == everyMonthSix) {
                    System.out.println("每月第一天和第六天执行任务");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            } finally {
                MAX_STOCK_COUNT.release();
                everPastMonthTask();
            }
        }
    };


    /**
     * 定时器每天四点触发，然后执行TodoEverPastTask，由TodoEverPastTask判断执行时机
     * scheduleAtFixedRate（执行任务，延迟时间，循环时间，时间单位）
     */
    public static void everPastMonthTask() {

        scheduler = Executors.newScheduledThreadPool(1);
        synchronized (scheduler) {
            long oneDay = 24 * 60 * 60 * 1000L;
            long initDelay = getTimeMillis("04:00:00") - System.currentTimeMillis();
            initDelay = initDelay > 0 ? initDelay : oneDay + initDelay;
            scheduler.scheduleAtFixedRate(
                    TodoEverPastTask,
                    initDelay,
                    oneDay,
                    TimeUnit.MILLISECONDS);
        }
    }

    /**
     * 停止定时器
     */
    private static void stop() {
        synchronized (scheduler) {
            if (scheduler != null && !scheduler.isShutdown()) {
                scheduler.shutdownNow();
                scheduler = null;
            }
        }
    }


    /**
     * 关闭同步信号量
     */
    public static void stopSemaphore() {
        synchronized (MAX_STOCK_COUNT) {
            if (MAX_STOCK_COUNT != null) {
                MAX_STOCK_COUNT.release();
            }
        }
    }

    /**
     * 重启定时器
     */
    public static void reStart() {
        stop();
        stopSemaphore();
        everPastMonthTask();
        everPresentDayTask();

    }

    /**
     * 触发定时任务
     */
    public static void trigger() {
        everPastMonthTask();
        everPresentDayTask();
    }


    /**
     * 时间格式转换成毫秒时间
     * @param time
     * @return
     */
    private static long getTimeMillis(String time) {
        try {
            DateFormat dateFormat = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
            DateFormat dayFormat = new SimpleDateFormat("yy-MM-dd");
            Date curDate = dateFormat.parse(dayFormat.format(new Date()) + " " + time);
            return curDate.getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0;
    }
}
